package com.guangfeng.yql.comm.netty.test;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import lombok.SneakyThrows;

import javax.tools.*;
import java.io.*;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;

public class DynamicClassLoader extends ClassLoader implements DiagnosticListener {
    @SneakyThrows
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {

        byte[] data = getData(name);
        if (data != null) {
            return defineClass(null, data, 0, data.length);
        }
        return super.findClass(name);
    }

    public byte[] getData(String className) throws Exception {
        InputStream in = null;
        ByteArrayOutputStream out = null;
        try {
            in = new FileInputStream(className);
            out = new ByteArrayOutputStream();
            IoUtil.copy(in, out);
            IoUtil.close(in);
            IoUtil.close(out);
            return out.toByteArray();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    @SneakyThrows
    public static void main(String[] args) throws IOException {
        String path = "D:\\Project\\fitness\\src\\main\\java\\com\\fitness\\common\\netty\\test\\testClassLoad.java";
       while (true){
           JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
           StandardJavaFileManager manager = javaCompiler.getStandardFileManager(null, null, StandardCharsets.UTF_8);
           Iterable<? extends JavaFileObject> fileObjects = manager.getJavaFileObjects(path);
           JavaCompiler.CompilationTask task = javaCompiler.getTask(null, manager, null, null, null, fileObjects);
           task.call();
           manager.close();
           DynamicClassLoader classLoader = new DynamicClassLoader();
           Class<?> loaderClass = classLoader.findClass(path.replaceAll("\\.java","\\.class"));
           if (loaderClass != null){
               Object instance = loaderClass.newInstance();
               Method test = loaderClass.getDeclaredMethod("test");
               if (instance instanceof Runnable){
                   Thread thread = new Thread((Runnable) instance);
                   thread.start();
               }
               test.invoke(loaderClass);
           }
           File file = FileUtil.file(path.replaceAll("\\.java", "\\.class"));
           file.delete();
           Thread.sleep(3000);
       }

    }

    /**
     * Invoked when a problem is found.
     *
     * @param diagnostic a diagnostic representing the problem that
     *                   was found
     * @throws NullPointerException if the diagnostic argument is
     *                              {@code null} and the implementation cannot handle {@code null}
     *                              arguments
     */
    @Override
    public void report(Diagnostic diagnostic) {
    }
}
